package com.iot.common.utils.device;

import com.iot.common.annotation.Excel;
import com.iot.common.core.domain.BaseEntity;
import com.iot.common.utils.StringUtils;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Cao.ning
 * @date 2022/4/22
 */
public class EntityUtils {

    /**
     * 获取两个对象比较结果
     * @param presentObj
     * @param originalObj
     * @return
     */
    public static List<PropertiesChange> getPropertiesChange(BaseEntity presentObj, BaseEntity originalObj){
        Assert.notNull(presentObj, "presentData must not be null");
        List<PropertiesChange> list = new ArrayList<>();
        if(StringUtils.isNull(originalObj)){
            try {
                originalObj = presentObj.getClass().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        if(classEquals(presentObj, originalObj)){
            for(Field field : presentObj.getClass().getDeclaredFields()){
                field.setAccessible(true);
                Excel excel = field.getAnnotation(Excel.class);
                String fieldName = field.getName();
                String description = excel == null ? fieldName : excel.name();
                PropertiesChange propertiesChange = new PropertiesChange();
                try {
                    Object presentPropData = field.get(presentObj);
                    Object originalPropData = field.get(originalObj);
                    if(presentPropData == null && originalPropData == null){
                        // 如果都是null
                        continue;
                    }else if(presentPropData != null && presentPropData.equals(originalPropData)){
                        // 如果相等
                        continue;
                    }else if((presentPropData != null && !presentPropData.equals(originalPropData)) || (presentPropData == null && originalPropData != null)){
                        // 如果新旧不相等
                        propertiesChange.setType("U");
                    }else if(presentPropData != null && originalPropData == null){
                        // 没有旧的，有新的
                        propertiesChange.setType("A");
                    }
                    propertiesChange.setDescription(description);
                    propertiesChange.setField(fieldName);
                    propertiesChange.setPresent(presentPropData == null ? "" : presentPropData.toString());
                    propertiesChange.setOriginal(originalPropData == null ? "" : originalPropData.toString());
                    list.add(propertiesChange);
                } catch (IllegalAccessException e) {
                    continue;
                }
            }
        }
        return list;
    }

    /**
     * 比较两个对象是否同类型
     * @param obj1
     * @param obj2
     * @return
     */
    public static boolean classEquals(Object obj1, Object obj2) {
        return obj1.getClass() == obj2.getClass();
    }

    public static class PropertiesChange {
        private String type;
        private String original;
        private String present;
        private String field;
        private String description;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getOriginal() {
            return original;
        }

        public void setOriginal(String original) {
            this.original = original;
        }

        public String getPresent() {
            return present;
        }

        public void setPresent(String present) {
            this.present = present;
        }

        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }
    }
}
